/* * Author: Chris Seguin * * This software has been developed under the copyleft * rules of the GNU General Public License. Please * consult the GNU General Public License for more * details about use and distribution of this software. */ package org.acm.seguin.pretty; import org.acm.seguin.parser.Token; /** * Prints a description from a java doc comment with HTML tags formatted. * *@author Chris Seguin *@created July 23, 1999 */ public class JavadocDescriptionPrinter { /*<Instance Variables>*/ private PrintData printData; private StringBuffer buffer; private int indent; private int mode; private boolean newline; private int owedLines; /*</Instance Variables>*/ /*<Class Variables>*/ private static int NORMAL = 0; private static int PARA = 1; private static int LIST = 2; private static int END_LIST = 3; private static int TABLE = 4; private static int END_TAG = 5; private static int LINE_BREAK = 6; private static int PREFORMATTED = 7; /*</Class Variables>*/ /*<Constructors>*/ /** * Constructor for the JavadocDescriptionPrinter object * *@param data Description of Parameter *@param description Description of Parameter */ public JavadocDescriptionPrinter(PrintData data, String description) { printData = data; buffer = new StringBuffer(description); indent = printData.getJavadocIndent(); newline = false; mode = NORMAL; } /** * Constructor for the JavadocDescriptionPrinter object * *@param data Description of Parameter *@param description Description of Parameter *@param initIndent Description of Parameter */ public JavadocDescriptionPrinter(PrintData data, String description, int initIndent) { printData = data; buffer = new StringBuffer(description); indent = initIndent; } /*</Constructors>*/ /*<Methods>*/ /** * This is the main program. */ public void run() { if (printData.isReformatComments()) { int MIN = printData.getJavadocWordWrapMinimum(); int MAX = printData.getJavadocWordWrapMaximum(); JavadocTokenizer tok = new JavadocTokenizer(buffer.toString()); mode = NORMAL; boolean first = true; while (tok.hasNext()) { Token nextToken = tok.next(); first = printToken(nextToken, MIN, MAX, first); } } else { maintainCurrentFormat(); } } /** * Indents the line and inserts the required "*" */ protected void indent() { if (printData.isCurrentSingle()) return; newline = true; printData.indent(); printData.appendComment(" *", PrintData.JAVADOC_COMMENT); if (printData.isReformatComments() && (mode != PREFORMATTED)) { for (int ndx = 0; ndx < indent; ndx++) { printData.space(); } } } /** * Certain tags require that we insert a new line after them. * *@param token the tag that we are considering *@return true if we just printed a space or a newline */ protected boolean startMode(String token) { if (startsWith(token, "<PRE") || startsWith(token, "<CODE")) { mode = PREFORMATTED; } else if (startsWith(token, "</PRE") || startsWith(token, "</CODE")) { mode = NORMAL; } else if (startsWith(token, "<P")) { mode = PARA; } else if (startsWith(token, "<BR")) { mode = LINE_BREAK; } else if (startsWith(token, "<UL")) { mode = LIST; indent(); indent += 2; return true; } else if (startsWith(token, "<OL")) { mode = LIST; indent(); indent += 2; return true; } else if (startsWith(token, "</UL")) { mode = END_LIST; indent -= 2; indent(); return true; } else if (startsWith(token, "</OL")) { mode = END_LIST; indent -= 2; indent(); return true; } else if (startsWith(token, "<LI")) { indent(); mode = END_TAG; return true; } else if (startsWith(token, "<TABLE")) { mode = TABLE; indent(); indent += 2; return true; } else if (startsWith(token, "<TR")) { mode = TABLE; indent(); indent += 2; return true; } else if (startsWith(token, "<TD")) { mode = TABLE; indent(); indent += 2; return true; } else if (startsWith(token, "<TH")) { mode = TABLE; indent(); indent += 2; return true; } else if (startsWith(token, "</TABLE")) { mode = TABLE; indent -= 2; indent(); return true; } else if (startsWith(token, "</TR")) { mode = TABLE; indent -= 2; indent(); return true; } else if (startsWith(token, "</TD")) { mode = TABLE; indent -= 2; indent(); return true; } else if (startsWith(token, "</TH")) { mode = TABLE; indent -= 2; indent(); return true; } else if (startsWith(token, "</") && !newline) { mode = END_TAG; } return false; } /** * Detects the end of the tag marker * *@param token the token *@return Description of the Returned Value */ protected boolean endMode(String token) { if (mode == END_TAG) { mode = NORMAL; printData.space(); return true; } if (mode == PARA) { mode = NORMAL; indent(); indent(); return true; } if (mode == LINE_BREAK) { mode = NORMAL; indent(); return true; } if (mode == LIST) { mode = NORMAL; } if (mode == END_LIST) { mode = NORMAL; indent(); return true; } if (mode == TABLE) { mode = NORMAL; indent(); return true; } return false; } /** * Checks to see if this tag is the same as what we want and ignores case * troubles * *@param have the token that we have *@param want the token that we are interested in *@return true if what we have is the same as what we want */ protected boolean startsWith(String have, String want) { return have.toUpperCase().startsWith(want); } /** * Description of the Method * *@param nextToken Description of Parameter *@param MIN Description of Parameter *@param MAX Description of Parameter *@param isFirst Description of Parameter *@return Description of the Returned Value */ private boolean printToken(Token nextToken, int MIN, int MAX, boolean isFirst) { if (nextToken.kind == JavadocTokenizer.WORD) { newline = false; int length = nextToken.image.length(); if ((printData.getLineLength() > MIN) && (printData.getLineLength() + length > MAX) && (mode != PREFORMATTED)) { indent(); newline = true; } if (nextToken.image.charAt(0) == '<') { newline = startMode(nextToken.image.toUpperCase()); } else { newline = false; } printData.appendComment(nextToken.image, PrintData.JAVADOC_COMMENT); if (nextToken.image.charAt(nextToken.image.length() - 1) == '>') { newline = endMode(nextToken.image) || newline; } return newline; } else { if (mode != PREFORMATTED) { if (!isFirst) { printData.space(); return true; } } else if (nextToken.kind == JavadocTokenizer.SPACE) { printData.appendComment(nextToken.image, PrintData.JAVADOC_COMMENT); } else { indent(); } return isFirst; } } /** * Maintains the current format */ private void maintainCurrentFormat() { JavadocTokenizer tok = new JavadocTokenizer(buffer.toString()); owedLines = 0; Token last = null; Token current = tok.next(); while (current.kind != JavadocTokenizer.WORD) { last = current; if (!tok.hasNext()) { return; } current = tok.next(); } if ((last != null) && (last.kind != JavadocTokenizer.NEWLINE)) { mcfOutputToken(last, printData); } mcfOutputToken(current, printData); while (tok.hasNext()) { Token nextToken = tok.next(); mcfOutputToken(nextToken, printData); } } /** * Description of the Method * *@param nextToken Description of Parameter *@param printData Description of Parameter */ private void mcfOutputToken(Token nextToken, PrintData printData) { if (nextToken.kind == JavadocTokenizer.NEWLINE) { owedLines++; } else { while (owedLines > 0) { indent(); owedLines--; } printData.appendComment(nextToken.image, PrintData.JAVADOC_COMMENT); } } /*</Methods>*/ }